#include "qresourcemanager.h"

#include <QFile>

#include <QFileInfo>
#include <QDir>

struct ResourceInfo
{
    QString     m_name;
    QByteArray  m_data;
    bool        m_system;
};

QResourceManager::QResourceManager()
{
}

QStringList QResourceManager::getTopLevelNames()
{
    return m_resources.keys();
}

QStringList QResourceManager::getResourceNames(const QString &topLevel)
{
    Resource r=m_resources.value(topLevel);
    return r.keys();
}


QStringList QResourceManager::getSelectNames()
{
    return m_selectList;
}

void QResourceManager::addSelect(const QString &name)
{
    m_selectList.append(name);
    m_selectList.removeDuplicates();
}

void QResourceManager::removeSelect(const QString &name)
{
    m_selectList.removeAll(name);
}

void QResourceManager::addTopLevel(const QString &name)
{
    if(m_resources.contains(name))
    {
        return;
    }
    Resource r;
    m_resources.insert(name,r);
}

void QResourceManager::removeTopLevel(const QString &name)
{
    m_resources.remove(name);
}

void QResourceManager::addResource(const QString &topLevel, const QString &name, const QByteArray &data)
{
    Resource r=m_resources.value(topLevel);

    ResourceInfo info;
    if(r.contains(name))
    {
        return;
    }
    info.m_data=data;
    info.m_name=name;
    info.m_system=false;
    r.insert(name,info);
    m_resources.insert(topLevel,r);
}

void QResourceManager::removeResource(const QString &topLevel, const QString &name)
{
    Resource r=m_resources.value(topLevel);
    r.remove(name);
    m_resources.insert(topLevel,r);
}

bool QResourceManager::topLevelCandel(const QString &topLevel)
{
    Resource r=m_resources.value(topLevel);

    QMap<QString,ResourceInfo>::const_iterator i = r.constBegin();
     while (i != r.constEnd())
     {
         ResourceInfo info=i.value();
         if(info.m_system)
         {
             return false;
         }
         ++i;
     }
     return true;
}

bool QResourceManager::resourceCandel(const QString &topLevel, const QString &name)
{
    Resource r=m_resources.value(topLevel);
    ResourceInfo info;
    if(!r.contains(name))
    {
        return false;
    }
    info=r.value(name);
    return !info.m_system;
}

void QResourceManager::initResource(QString path)
{
    m_path=path;

    QDir dir(path);
    QList<QFileInfo>    list=dir.entryInfoList();

    QString name;
    for(int i=0;i<list.size();i++)
    {
        name=list.at(i).fileName();
        if(name.endsWith(".res"))
        {
            QFile f(path+"/"+name);
            if(f.open(QFile::ReadOnly))
            {
                name=name.left(name.size()-4);



                QByteArray array=f.readAll();
                if(array.startsWith("qres"))
                {
                    Resource res;
                    array=array.mid(4);
                    int datasize;
                    int namesize;
                    array=array.mid(4);
                    while(1)
                    {
                        ResourceInfo rinfo;
                        datasize=getInt(array);
                        array=array.mid(4);
                        if(array.size()==0)
                        {
                            break;
                        }
                        namesize=getInt(array);
                        array=array.mid(4);
                        if(array.size()==0)
                        {
                            break;
                        }
                        rinfo.m_system=(getInt(array)==1);
                        array=array.mid(4);
                        if(array.size()==0)
                        {
                            break;
                        }

                        rinfo.m_name=(QString(array.left(namesize)));
                        array=array.mid(namesize);
                        if(array.size()==0)
                        {
                            break;
                        }
                        rinfo.m_data=array.left(datasize);
                        array=array.mid(datasize);

                        res.insert(rinfo.m_name,rinfo);

                        if(array.size()==0)
                        {
                            break;
                        }
                    }
                    m_resources.insert(name,res);
                }
            }
        }
    }

}

void QResourceManager::save(QString toplevel)
{

    if(toplevel!="")
    {
        QFile f(m_path+"/"+toplevel+".res");
        if(!m_resources.contains(toplevel))
        {
            f.remove();
            return;
        }
        if(!f.open(QFile::WriteOnly))
        {
            return;
        }
        f.resize(0);
        QByteArray buff;
        Resource r=m_resources.value(toplevel);
        buff.append("qres");
        writeInt(buff,r.size());

        QMap<QString,ResourceInfo>::const_iterator i = r.constBegin();
         while (i != r.constEnd())
         {
             ResourceInfo info=i.value();
             writeInt(buff,info.m_data.size());
             writeInt(buff,info.m_name.size());
             writeInt(buff,info.m_system?1:0);
             buff.append(info.m_name);
             buff.append(info.m_data);
             ++i;
         }
         f.write(buff);
         f.close();
    }
    else
    {
        QStringList keys=m_resources.keys();

        for(int i=0;i<keys.size();i++)
        {
            save(keys.at(i));
        }
    }
}

void QResourceManager::writeInt(QByteArray &array, int value)
{
    array.append((value>>24)&0xff);
    array.append((value>>16)&0xff);
    array.append((value>>8)&0xff);
    array.append((value)&0xff);
}

int QResourceManager::getInt(QByteArray &array)
{
    int ret;
    ret=((array[0]&0xff)<<24)+((array[1]&0xff)<<16)+((array[2]&0xff)<<8)+(array[3]&0xff);
    return ret;
}

QByteArray QResourceManager::getResourceData(const QString &topLevel, const QString &name)
{
    Resource    r=m_resources.value(topLevel);
    ResourceInfo info=r.value(name);
    return info.m_data;
}
